﻿using Acl.Diagnostics;
using Acl.Log;
using Acl.WinFormHosting;
using Acl.WinFormHosting.Internal;
using Acl.WinFormHosting.Services;

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace Microsoft.Extensions.Hosting;

/// <summary>
/// IHostBuilder的WinForm扩展
/// </summary>
public static class WinFormHostBuilderExtensions
{
    /// <summary>
    /// 配置单实例
    /// </summary>
    /// <param name="hostBuilder"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public static IHostBuilder ConfigureSingleInstance(this IHostBuilder hostBuilder)
    {
        // 单实例检查
        using var _singletonChecker = new SingletonProcessChecker();
        if (!_singletonChecker.IsPassed) throw new Exception("程序的一个实例已经在运行。");

        return hostBuilder;
    }

    /// <summary>
    /// 配置Acl 日志管理器
    /// </summary>
    /// <param name="builder"></param>
    /// <returns></returns>
    public static IHostBuilder ConfigureAclLog(this IHostBuilder builder)
    {
        builder.ConfigureLogging((context, logBuilder) =>
         {
             logBuilder.ConfigureAclLog();
         });

        return builder;
    }

    /// <summary>
    /// 配置Acl 日志管理器
    /// </summary>
    /// <param name="builder"></param>
    /// <returns></returns>
    private static ILoggingBuilder ConfigureAclLog(this ILoggingBuilder builder)
    {
        Acl.Log.LogManager.Initialize();

        LogManager.GetLogger("平台").Info("程序运行日志库完成初始化...");

        builder.ClearProviders();
        builder.AddProvider(AclLogProvider.Instance);


        return builder;
    }

    private const string WinFormsContextKey = "WinFormsContext";

    private static bool TryRetrieveWinFormsContext(this IDictionary<object, object> properties, out IWinFormsContext winFormsContext)
    {
        if (properties.TryGetValue(WinFormsContextKey, out var winFormsContextAsObject))
        {
            winFormsContext = (IWinFormsContext)winFormsContextAsObject;
            return true;
        }
        winFormsContext = new WinFormsContext();
        properties[WinFormsContextKey] = winFormsContext;
        return false;
    }

    /// <summary>
    /// 配置WinForms 应用程序
    /// </summary>
    /// <param name="hostBuilder"></param>
    /// <param name="configureAction"></param>
    /// <returns></returns>
    public static IHostBuilder ConfigureWinForms(this IHostBuilder hostBuilder, Action<IWinFormsContext>? configureAction = null) =>
       hostBuilder.ConfigureServices((hostBuilderContext, serviceCollection) =>
       {
           if (!TryRetrieveWinFormsContext(hostBuilder.Properties, out var winFormsContext))
           {
               serviceCollection
                   .AddSingleton(winFormsContext)
                   .AddSingleton(serviceProvider => new WinFormsThread(serviceProvider))
                   .AddHostedService<WinFormsHostedService>();
           }
           configureAction?.Invoke(winFormsContext);
       });

    /// <summary>
    /// 配置WinForms 应用程序,并指定WinForm的窗体
    /// </summary>
    /// <typeparam name="TForm"></typeparam>
    /// <param name="hostBuilder"></param>
    /// <param name="configureAction"></param>
    /// <returns></returns>

    public static IHostBuilder ConfigureWinForms<TForm>(this IHostBuilder hostBuilder, Action<IWinFormsContext>? configureAction = null) where TForm : Form, IMainForm =>
       hostBuilder
           .ConfigureWinForms(configureAction)
           .ConfigureServices((hostBuilderContext, serviceCollection) =>
           {
               serviceCollection.AddSingleton<TForm>();
               var shellInterfaceType = typeof(IMainForm);
               serviceCollection.AddSingleton(shellInterfaceType, serviceProvider => serviceProvider.GetRequiredService<TForm>());
           });

    /// <summary>
    /// 使用WinForm生命周期
    /// </summary>
    /// <param name="hostBuilder"></param>
    /// <remarks>* 关闭主窗体或调用Appliaction.Exit()之后生命结束</remarks>
    /// <returns></returns>
    public static IHostBuilder ConfigureWinFormsLifetime(this IHostBuilder hostBuilder) =>
      hostBuilder.ConfigureServices((hostBuilderContext, serviceCollection) =>
      {
          TryRetrieveWinFormsContext(hostBuilder.Properties, out var winFormsContext);
          winFormsContext.IsLifetimeLinked = true;
      });
}